package com.dong.user.client.filter;
import com.dong.thrift.user.dto.UserDTO;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;

import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;

public  abstract  class LoginFilter implements  Filter {
    private static Cache<String,UserDTO> cache = CacheBuilder.newBuilder().maximumSize(10000).expireAfterWrite(3, TimeUnit.MINUTES).build();
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        String token = req.getParameter("token");
        if(StringUtils.isBlank(token)) {
            Cookie[] cookies  = req.getCookies();
            for (Cookie cookie : cookies) {
                if(cookie.getName().equalsIgnoreCase("token")) {
                    token = cookie.getValue();
                    break;
                }
            }
        }
        UserDTO userDTO=null;
        if(StringUtils.isNotBlank(token)) {
            userDTO = cache.getIfPresent(token);
            if(userDTO==null) {
                userDTO = requestUserInfo(token);
                if(userDTO!=null) {
                    cache.put(token,userDTO);
                }
            }
        }
        if(userDTO==null) {
            resp.sendRedirect("http://www.dong.com/user/login");
            return;
        }
        cache.put(token,userDTO);
        login(req,resp,userDTO);
        chain.doFilter(request,response);

    }

    protected abstract void login(HttpServletRequest req, HttpServletResponse resp, UserDTO userDTO) ;
    protected abstract String userEdgeService();
    private UserDTO requestUserInfo(String token) {
        String url = "http://"+userEdgeService()+"/user/authentication";
        HttpClient client = new DefaultHttpClient();
        HttpPost post = new HttpPost(url);
        post.addHeader("token",token);
        InputStream is=null;
        try {
            HttpResponse resp = client.execute(post);
            if(resp.getStatusLine().getStatusCode()!= HttpStatus.SC_OK) {
                throw new RuntimeException("request user info failed! StatusLine: "+resp.getStatusLine());
            }
            is = resp.getEntity().getContent();
            byte[] buff = new byte[1024];
            StringBuilder builder = new StringBuilder();
            int len = 0;
            while(( len = is.read(buff))>0) {
                builder.append(new String(buff,0,len));
            }
            UserDTO userDTO = new ObjectMapper().readValue(builder.toString(),UserDTO.class);
            return userDTO;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(is!=null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return null;

    }
}
